/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.rie06.openvoip.sound;

//import javax.media.format.AudioFormat;
import javax.sound.sampled.*;

/**
 *
 * @author clement
 */
public class AudioSpecification {

    //http://xpose.avenir.asso.fr/viewxpose.php?site=8&subpage=/exemples/readercontrols.html
    private AudioFormat.Encoding encoding;
    private float rate;
    private int channels;
    private int frameSize;
    private int sampleSize;
    private boolean bigEndian;
    private TargetDataLine recordingLine;
    private SourceDataLine listeningLine;
    private AudioFormat format;
    private DataLine.Info info;
    public final int bufSize = 600;
    private boolean recording;
    private boolean pause;

    public AudioSpecification() {
//        encoding - A String that describes the encoding type for this AudioFormat.
//        sampleRate - The sample rate.
//        sampleSizeInBits - The sample size.
//        channels - The number of channels.
//        endian - The sample byte ordering used for this AudioFormat--BIG_ENDIAN or LITTLE_ENDIAN.
//        signed - Indicates whether the samples are stored in a signed or unsigned format. Specify true if the AudioFormat is signed, false if the AudioFormat is unsigned.
//        frameSizeInBits - The frame size.
//        frameRate - The frame rate.
//        dataType - The type of the data. For example, byte array.
        
        encoding = AudioFormat.Encoding.PCM_SIGNED;
        rate = 8000;
        channels = 1;
        frameSize = 4;
        sampleSize = 16;
        bigEndian = true;
        recordingLine = null;
        listeningLine = null;
        format = null;
        info = null;

        recording = false;
        pause = false;

        format = new AudioFormat(encoding, rate, sampleSize, channels, (sampleSize / 8)
                * channels, rate, bigEndian);
        
//        AudioFormat(java.lang.String encoding,
//                   double sampleRate,
//                   int sampleSizeInBits,
//                   int channels,
//                   int endian,
//                   int signed,
//                   int frameSizeInBits,
//                   double frameRate,
//                   java.lang.Class dataType)
        
    }

    protected int getBufSize() {
        return bufSize;
    }

    public SourceDataLine getListeningLine() {
        return listeningLine;
    }

    public void setListeningLine(SourceDataLine listeningLine) {
        this.listeningLine = listeningLine;
    }

    public TargetDataLine getRecordingLine() {
        return recordingLine;
    }

    public void setRecordingLine(TargetDataLine recordingLine) {
        this.recordingLine = recordingLine;
    }

    public boolean isPause() {
        return pause;
    }

    public void setPause(boolean pause) {
        this.pause = pause;
    }

    protected boolean isRecording() {
        return recording;
    }

    protected void setRecording(boolean recording) {
        this.recording = recording;
    }

    public AudioFormat getFormat() {
        return format;
    }

    protected boolean initRecordingLine() {
        // get and open the target data line for capture.
        boolean validated = true;
        info = new DataLine.Info(TargetDataLine.class, format);

        if (!AudioSystem.isLineSupported(info)) {
            System.out.println("Error: Line Unsupported");
            validated = false;
        } else {
            try {
                recordingLine = (TargetDataLine) AudioSystem.getLine(info);
                recordingLine.open(format, bufSize);
            } catch (LineUnavailableException ex) {
                System.out.println("Unable to open the line: " + ex);
                validated = false;
            } catch (SecurityException ex) {
                System.out.println(ex.toString());
                validated = false;
            } catch (Exception ex) {
                System.out.println(ex.toString());
                validated = false;
            }
        }
        return validated;
    }

    protected boolean initListeningLine() {
        // get and open the target data line for capture.
        boolean validated = true;

        info = new DataLine.Info(SourceDataLine.class, format);

        if (!AudioSystem.isLineSupported(info)) {
            System.out.println("Error: Line Unsupported");
            validated = false;
        } else {
            try {
                
                //test Mixer
//                for (Mixer.Info mixerInfo : AudioSystem.getMixerInfo()) {
//                    Mixer mixer = AudioSystem.getMixer(mixerInfo);
//                    try {
//                        listeningLine = (SourceDataLine) mixer.getLine(info);
//                        if (testControl(listeningLine)) {
//                            try{
//                            BooleanControl mute = (BooleanControl) listeningLine.getControl(BooleanControl.Type.MUTE);
//                            
//                            break;
//                            }catch(Exception ex){
//                                System.out.println(ex);
//                            }
//                        } else {
//                            System.out.println("Don't support all mixer features");
//                        }
//                    } catch (LineUnavailableException ex) {
//                        Logger.getLogger(AudioSpecification.class.getName()).log(Level.SEVERE, null, ex);
//                    }
//
//                }
                //end mixer test
                
                listeningLine = (SourceDataLine) AudioSystem.getLine(info);
                
                //FloatControl control = (FloatControl) listeningLine.getControl(FloatControl.Type.BALANCE);
                
                
                listeningLine.open(format, bufSize);
            } catch (LineUnavailableException ex) {
                System.out.println("Unable to open the line: " + ex);
                validated = false;
            } catch (SecurityException ex) {
                System.out.println(ex.toString());
                validated = false;
            } catch (Exception ex) {
                System.out.println(ex.toString());
                validated = false;
            }
        }
        return validated;
    }

    private boolean testControl(SourceDataLine line) {

        boolean testPassed = true;

        //récupération du contrôle de silence
        if (line.isControlSupported(BooleanControl.Type.MUTE)) {
            testPassed = false;
        }
        //recupération du contrôle de gain
        if (line.isControlSupported(FloatControl.Type.MASTER_GAIN)) {
            testPassed = false;
        }
        //Récupération du contrôle de balance
        if (line.isControlSupported(FloatControl.Type.PAN)) {
            testPassed = false;
        }
        //Récupération du contrôle de fréquence d'échnatillonage
        if (line.isControlSupported(FloatControl.Type.SAMPLE_RATE)) {
            testPassed = false;
        }
        return testPassed;
    }
}
